#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <cstring>

using namespace std;

int tickets = 1000;

#define THREAD_NUM 3

// pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // 这是一个全局的锁

class ThreadData
{
public:
    ThreadData(const string& s, pthread_mutex_t* pm)
        :tname(s)
        ,pmtx(pm)
    {}
    string tname;
    pthread_mutex_t* pmtx;
};

void* getTickets(void* args) // 多个执行流可能同时进入这个函数，这个函数就被重入了
{
    ThreadData* td = (ThreadData*)args;
    (void)args;
    while (true)
    {
        // pthread_mutex_lock(&mtx); // 加锁的同时也要注意解锁，这是一个全局变量
        pthread_mutex_lock(td->pmtx);
        // 临界区
        if (tickets > 0)
        {
            cout << td->tname << " : " << tickets << endl;
            tickets--;
            pthread_mutex_unlock(td->pmtx);
            // pthread_mutex_unlock(&mtx);
        }
        else
        {
            // pthread_mutex_unlock(&mtx);
            pthread_mutex_unlock(td->pmtx);
            break;
        }
        // 模拟后续动作
        usleep(1000);
        delete td;
    }
}



int main()
{
    pthread_mutex_t mtx;
    pthread_mutex_init(&mtx, nullptr);

    pthread_t t[THREAD_NUM];
    for (int i = 0; i < THREAD_NUM; i++)
    {
        string name = "thread ";
        name += to_string(i + 1);

        ThreadData* td = new ThreadData(name, &mtx);
        pthread_create(t + i, nullptr, getTickets, (void*)td);
    }

    for (int i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(t[i], nullptr);
    }

    pthread_mutex_destroy(&mtx);

    return 0;
}

// void* threadRoutine(void* args)
// {
//     // pthread_detach(pthread_self());

//     while (true)
//     {
//         cout << (char*)args << " running ..., new tid: " << pthread_self() << endl;
//         sleep(1);
//         break;
//     }

//     pthread_exit((void*)1);
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, (void*)"new thread");

//     while (true)
//     {
//         cout << "main thread running ..., main tid: " << pthread_self() << endl;
//         sleep(1);
//         break;
//     }

//     int n = pthread_join(tid, nullptr);
//     cout << "n: " << n << ", " << strerror(n) << endl; 

//     return 0;
// }



// void* threadRoutine(void* args)
// {
//     while (true)
//     {
//         cout << (char*)args << " running ..., new tid: " << pthread_self() << endl;
//         sleep(1);
//     }
//     cout << "new thread quit" << endl;

//     pthread_exit((void*)1);
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, (void*)"new thread");

//     int i = 0;
//     while (true)
//     {
//         cout << "main thread running ..., main tid: " << pthread_self() << endl;
//         sleep(1);
//         i++;
//         if (i == 5) break;
//     }

//     pthread_cancel(tid);
//     cout << "pthread_cancel: " << tid << endl;

//     void* ret = nullptr;
//     pthread_join(tid, (void**)&ret); // 默认会阻塞等待
//     // PTHREAD_CANCELED;

//     cout << "main thread wait success ... main quit, new thread quit code: " << (long long)ret << endl;

//     // for (int i = 0; i < 5; i++)
//     // {
//     //     cout << ret[i] << endl;
//     // }

//     return 0;
// }